/**************************************************************************** 
* 
* Copyright (c) 2022  C*Core -   All Rights Reserved  
* 
* THIS SOFTWARE IS DISTRIBUTED "AS IS," AND ALL WARRANTIES ARE DISCLAIMED, 
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* 
* PROJECT     : CCFC201XBC           
* DESCRIPTION : mpu demo code
* HISTORY     : 2022
* @file     mpu_demo.c
* @version  3.0
* @date     2022-10-27
* @brief    Initial version.
*
*****************************************************************************/
#include "mpu_demo.h"
#include "mpu_lld.h"
#include "led_hw.h"
#include "console.h"

#if 1U
#define cDEBUG      PSPRINTF
#else
#define cDEBUG(...)
#endif

static void LED_PASS(void)
{
    uint8_t i;
    for (i = 0U; i < 3U; i++)
    {
        LED_Set(LED1, 0);
        delayms(1000);
        LED_Set(LED1, 1);
        delayms(1000);
    }
}

static void LED_FAIL(void)
{
    uint8_t i;
    for (i = 0U; i < 3U; i++)
    {
        LED_Set(LED3, 0);
        delayms(1000);
        LED_Set(LED3, 1);
        delayms(1000);
    }
}

static const uint8_t RAM_LED_Code[] =
{
    0x18U, 0x21U, 0x06U, 0xE0U, 0x70U, 0x00U, 0x03U, 0xE8U, 0xD7U, 0x01U, 0x63U, 0x60U,
    0x71U, 0x18U, 0xE3U, 0xF9U, 0x5CU, 0x08U, 0x00U, 0x8CU, 0x63U, 0x60U, 0x71U, 0x18U,
    0xE3U, 0xF9U, 0x5CU, 0x08U, 0x00U, 0x8EU, 0x63U, 0x60U, 0x71U, 0x18U, 0xE3U, 0xF9U,
    0x5CU, 0x08U, 0x00U, 0x90U, 0x48U, 0x00U, 0x34U, 0x01U, 0x00U, 0x10U, 0xE8U, 0x51U,
    0x48U, 0x10U, 0x71U, 0x18U, 0xE3U, 0xF9U, 0x34U, 0x08U, 0x06U, 0x26U, 0x48U, 0x10U,
    0x71U, 0x18U, 0xE3U, 0xF9U, 0x34U, 0x08U, 0x06U, 0x27U, 0x48U, 0x10U, 0x71U, 0x18U,
    0xE3U, 0xF9U, 0x34U, 0x08U, 0x06U, 0x28U, 0x48U, 0x00U, 0xD6U, 0x01U, 0xE8U, 0x10U,
    0x48U, 0x00U, 0xD5U, 0x01U, 0xE8U, 0x05U, 0xC5U, 0x31U, 0x1CU, 0x03U, 0x00U, 0x01U,
    0xD5U, 0x01U, 0xC5U, 0x01U, 0x70U, 0x20U, 0x9DU, 0x0AU, 0xE4U, 0xF9U, 0xC6U, 0x31U,
    0x1CU, 0x03U, 0x00U, 0x01U, 0xD6U, 0x01U, 0xC6U, 0x31U, 0xC7U, 0x01U, 0x0CU, 0x03U,
    0xE4U, 0xEEU, 0x48U, 0x00U, 0x71U, 0x18U, 0xE3U, 0xF9U, 0x34U, 0x08U, 0x06U, 0x26U,
    0x48U, 0x00U, 0x71U, 0x18U, 0xE3U, 0xF9U, 0x34U, 0x08U, 0x06U, 0x27U, 0x48U, 0x00U,
    0x71U, 0x18U, 0xE3U, 0xF9U, 0x34U, 0x08U, 0x06U, 0x28U, 0x48U, 0x00U, 0xD6U, 0x01U,
    0xE8U, 0x10U, 0x48U, 0x00U, 0xD5U, 0x01U, 0xE8U, 0x05U, 0xC5U, 0x31U, 0x1CU, 0x03U,
    0x00U, 0x01U, 0xD5U, 0x01U, 0xC5U, 0x01U, 0x70U, 0x20U, 0x9DU, 0x0AU, 0xE4U, 0xF9U,
    0xC6U, 0x31U, 0x1CU, 0x03U, 0x00U, 0x01U, 0xD6U, 0x01U, 0xC6U, 0x31U, 0xC7U, 0x01U,
    0x0CU, 0x03U, 0xE4U, 0xEEU, 0x30U, 0x61U, 0x00U, 0x10U, 0x1CU, 0x03U, 0x00U, 0x01U,
    0x34U, 0x01U, 0x00U, 0x10U, 0x30U, 0x01U, 0x00U, 0x10U, 0x22U, 0x20U, 0xE4U, 0xADU,
    0x21U, 0xF1U, 0x00U, 0x04U
};

/**********************************************************
 * There are one regions overlap(default: supervisor mode)
 * area1:   0x4000E000 ~ 0x4000E200: ctl_val->RWX
 *********************************************************/
static void mpu_basic_func(uint32_t ctl_val)
{
    uint32_t data32 = 0, tmp = 0;

    cc_memcpy((uint8_t *)0x4000E000, (const uint8_t *)RAM_LED_Code, sizeof(RAM_LED_Code));

    /* area1: ctl_val */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD0, 0x4000E000, 0x4000E200 - 1) != 0U)
    {
        PSPRINTF("\n MPU 0 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD0, ctl_val);
    MPU_RGDn_WORD3_SET(MPU_RGD0, RGDn_VALID);    /* Region descriptor is valid */

    /* Enable the first 64K RWX permissions */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD1, SRAM0_ADDR_S, SRAM0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 1 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD1, M0SM_RWX_);
    MPU_RGDn_WORD3_SET(MPU_RGD1, RGDn_VALID);

    /* MPU */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD2, MPU_ADDR_S, MPU_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 2 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD2, RGDn_VALID);

    /* SIUL */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD3, SIUL_ADDR_S, SIUL_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 3 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD3, RGDn_VALID);

    /* Code flash memory array 0 */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD4, CFLASH0_ADDR_S, CFLASH0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 4 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD4, RGDn_VALID);

    /* MC RGM */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD5, MC_RGM_S, MC_RGM_E) != 0U)
    {
        PSPRINTF("\n MPU 5 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD5, RGDn_VALID);

    /* BAM */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD6, BAM_ADDR_S, BAM_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 6 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD6, RGDn_VALID);

    /* LinFlex0, for print */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD7, LINFLEX0_ADDR_S, LINFLEX0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 7 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD7, RGDn_VALID);

    /* Enable MPU */
    MPU_CESR_SET(CESR_MPU_EN|CESR_SPERR_All);
    data32 = MPU_GET_CESR(); /* PRQA S 2983 */

    /* W test */
    if ((ctl_val == M0SM_RWX) || (ctl_val == M0SM_RW) || (ctl_val == M0SM_W)     \
    || (ctl_val == M0SM_WX) || (ctl_val == M0SM_RW_) || (ctl_val == M0SM_RWX_))
    {
        (*(uint32_t *)(0x4000E1B0)) = 0xaabbccddU;
    }

    /* R test */
    if ((ctl_val == M0SM_RWX) || (ctl_val == M0SM_RX) || (ctl_val == M0SM_RW)    \
    || (ctl_val == M0SM_R) || (ctl_val == M0SM_RX_) || (ctl_val == M0SM_RW_)    \
    || (ctl_val == M0SM_RWX_))
    {
        tmp = (*(uint32_t *)(0x4000E1B0));
    }
    if (tmp != 0xaabbccddU)
    {
        cDEBUG("\n no R! / no W!\n");   /* LinFlex0 is enabled */
        LED_FAIL();                     /* SIUL is enabled */
    }
    else
    {
        cDEBUG("\n RW PASS!\n");        /* LinFlex0 is enabled */
        LED_PASS();                     /* SIUL is enabled */
    }

    /* X test */
    if ((ctl_val == M0SM_RWX) || (ctl_val == M0SM_RX) || (ctl_val == M0SM_X)     \
    || (ctl_val == M0SM_WX) || (ctl_val == M0SM_RX_) || (ctl_val == M0SM_RWX_))
    {
        (*((void (*)())(0x4000E000)))(); /* PRQA S 0305 */
        cDEBUG("\n X PASS!\n");
    }
    else
    {
        cDEBUG("\n no X!\n");
    }

    /* Disable MPU */
    MPU_CESR_SET(CESR_MPU_DIS);
}

/* @note  The current PID with its PIDMASK must be equal to 
 *          the region's PID with its PIDMASK.(Default: PID = 0)
 * @param pid: Process Identifier(0~15)
 *        pidMask: If a bit in the PIDMASK is set, then the corresponding 
 *                 bit of the PID is ignored in the comparison(0~15).
 *  */
static void mpu_pid_demo(uint8_t pid, uint8_t pidMask) /* PRQA S 3219 */
{
    uint32_t data32 = 0, tmp = 0;
    uint32_t pidConf;
    uint32_t id, mask;

    id = pid;
    mask = pidMask;

    pidConf = (id << 24) | (mask << 16);

    if (MPU_RGDnWord0Word1_Set(MPU_RGD0, 0x4000E000, 0x4000E100 - 1) != 0U)
    {
        PSPRINTF("\n MPU 0 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD0, M0SM_RWX|M0PE);      /* RWX, PID enable */
    MPU_RGDn_WORD3_SET(MPU_RGD0, pidConf|RGDn_VALID); /* PID, Region descriptor is valid */

    /* Enable the first 64K RWX permissions */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD1, SRAM0_ADDR_S, SRAM0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 1 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD1, RGDn_VALID);

    /* MPU */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD2, MPU_ADDR_S, MPU_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 2 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD2, RGDn_VALID);

    /* SIUL */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD3, SIUL_ADDR_S, SIUL_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 3 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD3, RGDn_VALID);

    /* Code flash memory array 0 */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD4, CFLASH0_ADDR_S, CFLASH0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 4 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD4, RGDn_VALID);

    /* BAM */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD6, BAM_ADDR_S, BAM_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 6 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD6, RGDn_VALID);

    /* LinFlex0, for print */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD7, LINFLEX0_ADDR_S, LINFLEX0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 7 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD7, RGDn_VALID);

    /* Enable MPU */
    MPU_CESR_SET(CESR_MPU_EN|CESR_SPERR_All);
    data32 = MPU_GET_CESR(); /* PRQA S 2983 */

    (*(uint32_t *)(0x4000E0B0)) = 0xaabbccddU;   /* if no W, will be stuck */
    tmp = (*(uint32_t *)(0x4000E0B0));          /* if no R, will be stuck */
    if (tmp != 0xaabbccddU)
    {
        cDEBUG("\n mpu_pid_demo Test Fail!\n"); /* LinFlex0 is enabled */
        LED_FAIL();                             /* SIUL is enabled */
    }
    else
    {
        cDEBUG("\n mpu_pid_demo Test Pass!\n"); /* LinFlex0 is enabled */
        LED_PASS();                             /* SIUL is enabled */
    }

    /* Disable MPU */
    MPU_CESR_SET(CESR_MPU_DIS);
}

/**********************************************************
 * There are two regions overlap(default: supervisor mode)
 * area1:   0x4000E000 ~ 0x4000E100 WX
 * area2:   0x4000E0A0 ~ 0x4000E200 RX
 * overlap  0x4000E0A0 ~ 0x4000E100 RWX
 *********************************************************/
static void mpu_overlap_demo1(void) /* PRQA S 3219 */
{
    uint32_t data32 = 0, tmp = 0;

    /* area1: WX */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD0, 0x4000E000, 0x4000E100 - 1) != 0U)
    {
        PSPRINTF("\n MPU 0 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD0, M0SM_WX);
    MPU_RGDn_WORD3_SET(MPU_RGD0, RGDn_VALID);    /* Region descriptor is valid */

    /* Enable the first 64K RWX permissions */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD1, SRAM0_ADDR_S, SRAM0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 1 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD1, RGDn_VALID);

    /* MPU */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD2, MPU_ADDR_S, MPU_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 2 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD2, RGDn_VALID);

    /* SIUL */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD3, SIUL_ADDR_S, SIUL_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 3 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD3, RGDn_VALID);

    /* Code flash memory array 0 */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD4, CFLASH0_ADDR_S, CFLASH0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 4 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD4, RGDn_VALID);

    /* area2: RX */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD5, 0x4000E0A0, 0x4000E200 - 1) != 0U)
    {
        PSPRINTF("\n MPU 5 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD5, M0SM_RX);
    MPU_RGDn_WORD3_SET(MPU_RGD5, RGDn_VALID);    /* Region descriptor is valid */

    /* BAM */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD6, BAM_ADDR_S, BAM_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 6 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD6, RGDn_VALID);

    /* LinFlex0, for print */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD7, LINFLEX0_ADDR_S, LINFLEX0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 7 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD7, RGDn_VALID);

    /* Enable MPU */
    MPU_CESR_SET(CESR_MPU_EN|CESR_SPERR_All);
    data32 = MPU_GET_CESR(); /* PRQA S 2983 */

    /* overlap area: RWX */
    (*(uint32_t *)(0x4000E0B0)) = 0xaabbccddU;           /* if no W, will be stuck */
    tmp = (*(uint32_t *)(0x4000E0B0));                  /* if no R, will be stuck */
    if (tmp != 0xaabbccddU)
    {
        cDEBUG("\n mpu_overlap_demo1 Test Fail!\n");    /* LinFlex0 is enabled */
        LED_FAIL();                                     /* SIUL is enabled */
    }
    else
    {
        cDEBUG("\n mpu_overlap_demo1 Test Pass!\n");    /* LinFlex0 is enabled */
        LED_PASS();                                     /* SIUL is enabled */
    }

    /* if no W, will be stuck */
    cc_memcpy((uint8_t *)0x4000E000, (const uint8_t *)RAM_LED_Code, sizeof(RAM_LED_Code));
    delayms(10);
    /* if no X, will be stuck */
    (*((void (*)())(0x4000E000)))(); /* PRQA S 0305 */

    /* Disable MPU */
    MPU_CESR_SET(CESR_MPU_DIS);
}

/**********************************************************
 * There are three regions overlap(default: supervisor mode)
 * area1:   0x4000E000 ~ 0x4000E300 X
 * area2:   0x4000E100 ~ 0x4000E400 R
 * area3:   0x4000E200 ~ 0x4000E500 W
 * overlap  0x4000E200 ~ 0x4000E300 RWX
 *********************************************************/
static void mpu_overlap_demo2(void) /* PRQA S 3219 */
{
    uint32_t data32 = 0, tmp = 0;

    /* area1: X */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD0, 0x4000E000, 0x4000E300 - 1) != 0U)
    {
        PSPRINTF("\n MPU 0 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD0, M0SM_X);
    MPU_RGDn_WORD3_SET(MPU_RGD0, RGDn_VALID);    /* Region descriptor is valid */

    /* Enable the first 64K RWX permissions */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD1, SRAM0_ADDR_S, SRAM0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 1 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD1, RGDn_VALID);

    /* MPU */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD2, MPU_ADDR_S, MPU_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 2 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD2, RGDn_VALID);

    /* SIUL */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD3, SIUL_ADDR_S, SIUL_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 3 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD3, RGDn_VALID);

    /* Code flash memory array 0 */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD4, CFLASH0_ADDR_S, CFLASH0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 4 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD4, RGDn_VALID);

    /* area2: R */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD5, 0x4000E100, 0x4000E400 - 1) != 0U)
    {
        PSPRINTF("\n MPU 5 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD5, M0SM_R);
    MPU_RGDn_WORD3_SET(MPU_RGD5, RGDn_VALID);    /* Region descriptor is valid */

    /* BAM */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD6, BAM_ADDR_S, BAM_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 6 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD6, RGDn_VALID);

    /* area3: W */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD7, 0x4000E200, 0x4000E500 - 1) != 0U)
    {
        PSPRINTF("\n MPU 7 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD7, M0SM_W);
    MPU_RGDn_WORD3_SET(MPU_RGD7, RGDn_VALID);

    /* Enable MPU */
    MPU_CESR_SET(CESR_MPU_EN|CESR_SPERR_All);
    data32 = MPU_GET_CESR(); /* PRQA S 2983 */

    /* overlap area: RWX */
    (*(uint32_t *)(0x4000E2A0)) = 0xaabbccddU;           /* if no W, will be stuck */
    tmp = (*(uint32_t *)(0x4000E2A0));                  /* if no R, will be stuck */
    if (tmp != 0xaabbccddU)
    {
        LED_FAIL();                                     /* SIUL is enabled */
    }
    else
    {
        LED_PASS();                                     /* SIUL is enabled */
    }

    /* if no W, will be stuck */
    cc_memcpy((uint8_t *)0x4000E200, (const uint8_t *)RAM_LED_Code, sizeof(RAM_LED_Code));
    delayms(10);
    /* if no X, will be stuck */
    (*((void (*)())(0x4000E200)))(); /* PRQA S 0305 */

    /* Disable MPU */
    MPU_CESR_SET(CESR_MPU_DIS);

    while (1)
    {
        /* Prevents access to print functions */
        LED_Set(LED2, 0);
        delayms(1000);
        LED_Set(LED2, 1);
        delayms(1000);
    }
}

/**********************************************************
 * There are two regions overlap(default: supervisor mode)
 * area1:   0x4000E000 ~ 0x4000E100 W
 * area2:   0x4000E0A0 ~ 0x4000E200 R
 * overlap  0x4000E0A0 ~ 0x4000E100 RW
 *********************************************************/
static void mpu_overlap_demo3(void) /* PRQA S 3219 */
{
    uint32_t data32 = 0, tmp = 0;

    /* area1: WX */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD0, 0x4000E000, 0x4000E100 - 1) != 0U)
    {
        PSPRINTF("\n MPU 0 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD0, M0SM_W);
    MPU_RGDn_WORD3_SET(MPU_RGD0, RGDn_VALID);    /* Region descriptor is valid */

    /* Enable the first 64K RWX permissions */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD1, SRAM0_ADDR_S, SRAM0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 1 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD1, RGDn_VALID);

    /* MPU */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD2, MPU_ADDR_S, MPU_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 2 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD2, RGDn_VALID);

    /* SIUL */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD3, SIUL_ADDR_S, SIUL_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 3 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD3, RGDn_VALID);

    /* Code flash memory array 0 */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD4, CFLASH0_ADDR_S, CFLASH0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 4 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD4, RGDn_VALID);

    /* area2: RX */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD5, 0x4000E0A0, 0x4000E200 - 1) != 0U)
    {
        PSPRINTF("\n MPU 5 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD2_SET(MPU_RGD5, M0SM_R);
    MPU_RGDn_WORD3_SET(MPU_RGD5, RGDn_VALID);    /* Region descriptor is valid */

    /* BAM */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD6, BAM_ADDR_S, BAM_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 6 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD6, RGDn_VALID);

    /* LinFlex0, for print */
    if (MPU_RGDnWord0Word1_Set(MPU_RGD7, LINFLEX0_ADDR_S, LINFLEX0_ADDR_E) != 0U)
    {
        PSPRINTF("\n MPU 7 Address set error!\n");
        LED_FAIL();
    }
    MPU_RGDn_WORD3_SET(MPU_RGD7, RGDn_VALID);

    /* Enable MPU */
    MPU_CESR_SET(CESR_MPU_EN|CESR_SPERR_All);
    data32 = MPU_GET_CESR(); /* PRQA S 2983 */

    /* overlap area: RWX */
    (*(uint32_t *)(0x4000E0B0)) = 0xaabbccddU;           /* if no W, will be stuck */
    tmp = (*(uint32_t *)(0x4000E0B0));                  /* if no R, will be stuck */
    if (tmp != 0xaabbccddU)
    {
        cDEBUG("\n mpu_overlap_demo3 Test Fail!\n");    /* LinFlex0 is enabled */
        LED_FAIL();                                     /* SIUL is enabled */
    }
    else
    {
        cDEBUG("\n mpu_overlap_demo3 Test Pass!\n");    /* LinFlex0 is enabled */
        LED_PASS();                                     /* SIUL is enabled */
    }

    /* if no W, will be stuck */
    cc_memcpy((uint8_t *)0x4000E000, (const uint8_t *)RAM_LED_Code, sizeof(RAM_LED_Code));
    delayms(10);
    /* no X, error */
    (*((void (*)())(0x4000E000)))(); /* PRQA S 0305 */

    /* Disable MPU */
    MPU_CESR_SET(CESR_MPU_DIS);
}

void MPU_Test_Demo(void)
{
#if MPU_BASE_FUNC_DEMO1_SW
    mpu_basic_func(M0SM_RWX);
#endif

#if MPU_BASE_FUNC_DEMO2_SW
    mpu_basic_func(M0SM_R);
#endif

#if MPU_BASE_FUNC_DEMO3_SW
    mpu_basic_func(M0SM_W);
#endif

#if MPU_BASE_FUNC_DEMO4_SW
    mpu_basic_func(M0SM_X);
#endif

#if MPU_PID_DEMO1_SW
    /* PID = 0(Default) */
    mpu_pid_demo(0x00, 0x00);
#endif

#if MPU_PID_DEMO2_SW
    mpu_pid_demo(0xFF, 0x00); /* Error: enter abnormal interrupt */
#endif

#if MPU_PID_DEMO3_SW
    /* mask = 0xFF */
    mpu_pid_demo(0xFF, 0xFF);
#endif

#if MPU_OVERLAP_DEMO1_SW
    mpu_overlap_demo1();
#endif

#if MPU_OVERLAP_DEMO2_SW
    mpu_overlap_demo2();
#endif

#if MPU_OVERLAP_DEMO3_SW
    mpu_overlap_demo3();    /* no X, error, enter abnormal interrupt */
#endif
}


